package com.yin.myproject.thread.listblock;

import com.yin.myproject.thread.spinlock.Lock;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 有界队列锁,使用一个volatile数组来组织线程
 * 缺点是得原先知道线程的规模n,所有线程获取同一个锁的次数不能超过n
 * 假设L把锁,那么锁的空间复杂度为O(Ln)
 *
 * @author Eason
 * @create 2018-03-07 16:24
 **/
public class ArrayLock implements Lock {

    //总容量
    private final int capacity;
    // 使用volatile数组来存放锁标志， flags[i] = true表示可以获得锁
    private volatile boolean[] flags;
    // 指向新加入的节点的后一个位置
    private AtomicInteger tail;

    private ThreadLocal<Integer> mySlotIndex = ThreadLocal.withInitial(() -> 0);

    public ArrayLock(int capacity) {
        this.capacity = capacity;
        flags = new boolean[capacity];
        tail = new AtomicInteger(0);
        flags[0] = true;
    }

    @Override
    public void lock() {
        int slot = tail.getAndIncrement() % capacity;
        mySlotIndex.set(slot);
        while (!flags[slot]) {

        }
    }

    @Override
    public void unlock() {
        int slot = mySlotIndex.get();
        flags[slot] = false;
        flags[slot + 1 % capacity] = true;
    }

    @Override
    public String toString() {
        return "ArrayLock";
    }
}
